package com.huai.jt1078.utils;

import cn.hutool.core.text.StrSpliter;
import com.huai.jt1078.entity.AudioTag;
import com.huai.jt1078.entity.SpsFrame;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import cn.hutool.core.util.StrUtil;

/**
 * @author xingkong
 * @program jt1078
 * @description Byte读取工具类
 * @date 2021-09-04 11:03
 **/
public class ByteUtil {

    /**
     * 返回一个bcd 高四位为一个数字 第四位为一个数字
     *
     * @param b 字节
     * @return bcd字符串
     */
    public static String getBcd(byte b) {
        int ch1 = (b >> 4) & 0x0f;
        int ch2 = (b & 0x0f);
        return ch1 + "" + ch2;
    }

    /**
     * @param data 待转换数据
     * @return 字节数组
     * @author xingkong
     * @date 2021/9/7
     */
    public static byte[] getThreeBytes(Integer data) {
        byte[] bytes = new byte[3];
        bytes[0] = (byte) ((data >> 16) & 0xff);
        bytes[1] = (byte) ((data >> 8) & 0xff);
        bytes[2] = (byte) (data & 0xff);
        return bytes;
    }

    /**
     * 数组转换成十六进制字符串
     *
     * @param array 字节数组
     * @return HexString
     */
    public static String bytes2HexStr(byte[] array) {
        if (null == array || array.length < 1) {
            return "";
        }
        StringBuilder sb = new StringBuilder(array.length);
        String sTemp;
        for (byte b : array) {
            sTemp = Integer.toHexString(0xff & b);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 数组转换成带0x的十六进制字符串
     *
     * @param array
     * @return HexString
     */
    public static String bytes2FullHexStr(byte[] array) {
        StringBuilder sb = new StringBuilder(array.length);
        sb.append("0x");
        String sTemp;
        for (int i = 0; i < array.length; i++) {
            sTemp = Integer.toHexString(0xFF & array[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp);
            if (i < array.length - 1) {
                sb.append("0x");
            }
        }
        return sb.toString().toLowerCase();
    }


    /**
     * 把16进制字符串转换成字节数组
     *
     * @param hex 16进制字符串
     * @return byte[]
     */
    public static byte[] hexStr2Bytes(String hex) {
        if (StrUtil.isBlank(hex)) {
            return new byte[0];
        }
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
        }
        return result;
    }

    /**
     * 相当于(short *) byte_pointer的效果
     *
     * @param src 输入的字节数组
     * @return 字节数组
     * @author xingkong
     * @date 2021-09-07 15:53
     */
    public static short[] toShortArray(byte[] src) {
        short[] dst = new short[src.length / 2];
        for (int i = 0, k = 0; i < src.length; ) {
            dst[k++] = (short) ((src[i++] & 0xff) | ((src[i++] & 0xff) << 8));
        }
        return dst;
    }

    /**
     * 读取bytebuf剩下的字节
     *
     * @param msg 可读取bytebuf
     * @return 剩下所有的字节
     * @author xingkong
     * @date 2021-09-07 16:15
     */
    public static byte[] readReadableBytes(ByteBuf msg) {
        byte[] content = new byte[msg.readableBytes()];
        msg.readBytes(content);
        msg.release();
        return content;
    }

    /**
     * Flv 音频封装编码
     *
     * @param audioTag 音频tag
     * @return 字节流
     * @author xingkong
     * @date 2021-09-07 17:02
     */
    public static ByteBuf encode(AudioTag audioTag) throws Exception {
        ByteBuf buffer = Unpooled.buffer();
        if (audioTag == null) {
            return buffer;
        }
        //----------------------tag header begin-------
        buffer.writeByte(8);
        buffer.writeMedium(audioTag.getTagDataSize());
        buffer.writeMedium(audioTag.getOffSetTimestamp() & 0xFFFFFF);
        buffer.writeByte(audioTag.getOffSetTimestamp() >> 24);
        buffer.writeMedium(audioTag.getStreamId());
        //---------------------tag header length 11---------
        //---------------------tag header end----------------
        byte formatAndRateAndSize = (byte) (audioTag.getFormat() << 4 | audioTag.getRate() << 2 | audioTag.getSize() << 1 | audioTag.getType());
        //-------------data begin-------
        buffer.writeByte(formatAndRateAndSize);
        buffer.writeBytes(audioTag.getData());
        //-------------data end  -------
        //应该等于11+tagDataSize
        buffer.writeInt(buffer.writerIndex());
        return buffer;
    }

    /**
     * 转换数据 转换为我们需要的报文形式
     *
     * @param data 带转换的报文
     * @return 转换好的报文
     * @author xingkong
     * @date 2021/9/8
     */
    public static byte[] make(byte[] data) {
        ByteBuf buffer = Unpooled.buffer();
        buffer.writeBytes(String.format("%x\r\n", data.length).getBytes());
        buffer.writeBytes(data);
        buffer.writeByte((byte) '\r');
        buffer.writeByte((byte) '\n');
        return ByteUtil.readReadableBytes(buffer);
    }


    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 获取sps中包含的视频宽度
     *
     * @param sps sps信息
     * @return 返回视频宽度
     * @author xingkong
     * @date 2021-09-13 14:40
     */
    public static int getWidth(byte[] sps) {
        SpsFrame spsFrame = new SpsFrame().getSpsFrame(sps);
        H264SPSPaser analysis = new H264SPSPaser();
        return analysis.getWidth(spsFrame);
    }

    /**
     * 获取sps中包含的视频高度
     *
     * @param sps sps信息
     * @return 返回视频高度
     * @author xingkong
     * @date 2021-09-13 14:40
     */
    public static int getHeight(byte[] sps) {
        SpsFrame spsFrame = new SpsFrame().getSpsFrame(sps);
        H264SPSPaser analysis = new H264SPSPaser();
        return analysis.getHeight(spsFrame);
    }

    /**
     * 根据字符串返回6个字节的BCD
     *
     * @param s 输入的字符串
     * @return 6个字节的BCD
     * @author xingkong
     * @date 2021-09-16 10:58
     */
    public static byte[] setBcd(String s,int size) {
        String[] strings = StrSpliter.splitByLength(s, 2);
        byte[] bytes = new byte[size];
        for (int i = 0; i < size; i++) {
            bytes[i] = Byte.parseByte(strings[i]);
        }
        return bytes;
    }

    /**
     * 把 1 0 0 0数据转换为 0 0 0 1 并且转换为int
     * @param
     * @author xingkong
     * @date 2022-01-04 14:15
     * @return
     */
    public static int readIntDesc(ByteBuf buffer){
        byte[] bytes = new byte[4];
        byte[] desc = new byte[4];
        buffer.readBytes(bytes);
        for (int i = 0; i < 4; i++) {
            desc[i] = bytes[4 - i - 1];
        }
        return bytes2int(desc);
    }


    /**
     * byte to int
     *
     * @param data
     * @return
     */
    public static int bytes2int(byte[] data) {
        int mask = 0xff;
        int temp = 0;
        int n = 0;
        for (int i = 0; i < data.length; i++) {
            n <<= 8;
            temp = data[i] & mask;
            n |= temp;
        }
        return n;
    }
}
